﻿using System.IO;

namespace ZProto
{
    public class CsGenerator : ICodeGenerator
    {
        public string TypeFileName
        {
            get => $"{_type.Name}.cs";
        }
        public string WriterFileName
        {
            get => $"{_type.Name}BuffWriter.cs";
        }
        public string ReaderFileName
        {
            get => $"{_type.Name}BuffReader.cs";
        }
        private int _level;
        private TextWriter _writer;
        private ProtoType _type;
        public void BeginWriter(TextWriter writer)
        {
            _writer = writer;
            Line($"namespace ZProto.Message");
            LineAndUpLv("{");
        }
        public void EndWriter()
        {
            DownLvAndLine("}");
            _writer = null;
        }
        private void Line(string line)
        {
            if (_level > 0)
            {
                var lv = "".PadLeft(_level*4, ' ');
                _writer.WriteLine(lv + line);
            }
            else
            {
                _writer.WriteLine(line);
            }
        }
        private void LineAndUpLv(string line)
        {
            Line(line);
            _level++;
        }
        private void DownLvAndLine(string line)
        {
            _level--;
            Line(line);
        }
        public void GenerateProtoType()
        {
            Line($"public {_type.Tpye} {_type.Name}");
            LineAndUpLv("{");
            for (var i = 0; i < _type.Fields.Length; ++i)
            {
                var field = _type.Fields[i];
                if (field.IsArray)
                {
                    Line($"public {field.Type}[] {field.Name};");
                }
                else
                {
                    Line($"public {field.Type} {field.Name};");
                }
            }
            DownLvAndLine("}");
        }
        public void GenerateProtoWriter()
        {
            Line($"public static class {_type.Name}BuffWriter ");
            LineAndUpLv("{");
            Line($"public static void _{_type.Name}(this BuffWriter writer, {_type.Name} value)");
            LineAndUpLv("{");
            for (var i = 0; i < _type.Fields.Length; ++i)
            {
                var field = _type.Fields[i];
                if (field.IsArray)
                {
                    Line($"writer._array(value.{field.Name},writer._{field.Type});");
                }
                else
                {
                    Line($"writer._{field.Type}(value.{field.Name});");
                }
            }
            DownLvAndLine("}");
            DownLvAndLine("}");
        }
        public void GenerateProtoReader()
        {
            Line($"public static class {_type.Name}BuffReader ");
            LineAndUpLv("{");
            Line($"public static {_type.Name} _{_type.Name}(this BuffReader reader)");
            LineAndUpLv("{");
            Line($"{_type.Name} value = new {_type.Name}();");
            for (var i = 0; i < _type.Fields.Length; ++i)
            {
                var field = _type.Fields[i];
                if (field.IsArray)
                {
                    Line($"value.{field.Name} = reader._array(reader._{field.Type});");
                }
                else
                {
                    Line($"value.{field.Name} = reader._{field.Type}();");
                }
            }
            Line($"return value;");
            DownLvAndLine("}");
            DownLvAndLine("}");
        }
        public void BeginType(ProtoType type)
        {
            _type = type;
        }
        public void EndType()
        {
            _type = null;
        }
    }
}
